package com.sunday.common.statemachine.study.e11_Using_Actions;

import org.springframework.context.annotation.Bean;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.action.SpelExpressionAction;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;


/**
 * <a href="https://docs.spring.io/spring-statemachine/docs/4.0.0/reference/index.html#sm-actions">...</a>
 *
 * @author sunday
 * @since 2024/12/6
 */
public class Config7 extends StateMachineConfigurerAdapter<States, Events> {

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states
                .withStates()
                .initial(States.SI)
                .state(States.S1, action1(), action2())
                .state(States.S2, action1(), action2())
                .state(States.S3, action1(), action3());
    }

    @Bean
    public Action<States, Events> action1() {
        return new Action<States, Events>() {

            @Override
            public void execute(StateContext<States, Events> context) {
            }
        };
    }

    @Bean
    public BaseAction action2() {
        return new BaseAction();
    }

    @Bean
    public SpelAction action3() {
        ExpressionParser parser = new SpelExpressionParser();
        return new SpelAction(
                parser.parseExpression(
                        "stateMachine.sendEvent(T(org.springframework.statemachine.docs.Events).E1)"));
    }

    public class BaseAction implements Action<States, Events> {

        @Override
        public void execute(StateContext<States, Events> context) {
        }
    }

    public class SpelAction extends SpelExpressionAction<States, Events> {

        public SpelAction(Expression expression) {
            super(expression);
        }
    }

    /*
     * 带有操作的 SPEL 表达式
     * 您还可以使用 SPEL 表达式来替代 完全实施。Action
     *
     * 反应式操作
     * Normal interface 是一种简单的函数式方法，取回 void。在你阻止之前，这里没有任何阻碍 在方法本身中，这是一个有点问题，因为框架不能 了解它内部到底发生了什么。ActionStateContext
     *
     * public interface Action<S, E> {
     * 	void execute(StateContext<S, E> context);
     * }
     *
     * 为了解决这个问题，我们在内部将处理方式更改为 处理普通 Java 的 take 和 return .这样我们就可以调用 action 并完全以响应式方式 execute 操作，仅当它被订阅且以非阻塞方式执行 等待完成。ActionFunctionStateContextMono
     *
     * public interface ReactiveAction<S, E> extends Function<StateContext<S, E>, Mono<Void>> {
     * }
     *
     * 内部旧接口由 Reactor Mono Runnable 包装，因为它 共享相同的 return 类型。我们无法控制您在该方法中做什么！Action
     */

}
